<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // bind
        Function.prototype.customBind = function (context, ...bindArg) {
            const self = this;
            return function (...args) {
                const newArgs = bindArg.concat(args);
                return self.apply(context, newArgs);
            }
        }

        function fn(a, b, c) {
            console.log(this, a, b, c);
        }
        const fn1 = fn.customBind({ x: 1212 }, 1, 2, 3);
        fn1(20, 30);

        // call
        Function.prototype.customCall = function (context, ...agrs) {
            if (context === null) context = globalThis
            if (typeof context !== 'object') context = new Object(context)
            const fnKey = Symbol()
            context[fnKey] = this
            const res = context[fnKey](...agrs)
            delete context[fnKey]
            return res
        }
        function fn2(a, b, c) {
            console.log(this, a, b, c);
        }
        fn2.customCall({ x: 121212 }, 10, 20, 30)

        //apply
        Function.prototype.customApply = function (context, agrs) {
            if (context === null) context = globalThis
            if (typeof context !== 'object') context = new Object(context)
            const fnKey = Symbol()
            context[fnKey] = this
            const res = context[fnKey](...agrs)
            delete context[fnKey]
            return res
        }
        function fn3(a, b, c) {
            console.log(this, a, b, c);
        }
        fn3.customApply({ a: 'zs' }, [1, 2, 3])
    </script>
</body>

</html>